package user

import (
	"github.com/labstack/echo"
	auth "tacitus/library/authorized"
	"tacitus/library/error"
	"tacitus/library/format"
	resp "tacitus/library/response"
	"time"
)

func RegisterHandler(c echo.Context) error {
	i := new(struct{
		Account  string `json:"account"` // 帐号，不能重复
		Password string `json:"password"` // 密码，只能保存加密后的密码
	})
	if err := c.Bind(i); err != nil {
		return err
	}

	if ok, err := x.Exist(&User{Account:i.Account}); err != nil {
		return errs.Report("xorm", err)
	} else if ok {
		return errs.Called("用户帐号已存在")
	}

	salt := RandSlat()
	u := &User{
		Account:    i.Account,
		Password:   EncryptPassword(i.Password, salt),
		Salt:       salt,
		CreateTime: time.Now().Unix(),
	}
	if _, err := x.Insert(u); err != nil {
		return errs.Report("xorm", err)
	}

	// 调用监听者
	for _, lr := range RegisterListenerList {
		if err := lr(u); err != nil {
			return err
		}
	}
	return resp.Success(c)
}

func LoginHandler(c echo.Context) error {
	i := new(struct{
		Account  string `json:"account"` // 帐号，不能重复
		Password string `json:"password"` // 密码，只能保存加密后的密码
	})
	if err := c.Bind(i); err != nil {
		return err
	}

	u := new(User)
	if ok, err := x.Where("account = ? OR mobile = ?", i.Account, i.Account).Get(u); err != nil {
		return errs.Report("xorm", err)
	} else if !ok {
		return errs.Called("用户帐号不存在")
	}

	if EncryptPassword(i.Password, u.Salt) != u.Password {
		return errs.Called("帐号密码错误")
	}

	token := auth.Generate(auth.Claims{
		UserID:            u.ID,
		Account:           u.Account,
		AccessControlList: "*",
		Extends:           nil,
	})
	login := &Login{
		UserID:     u.ID,
		IP:         c.RealIP(),
		Token:      token,
		CreateTime: time.Now().Unix(),
	}
	if _, err := x.Insert(login); err != nil {
		return err
	}
	return resp.Data(c, echo.Map{
		"token": token,
	})
}

type Info struct {
	Account  string `json:"account"` // 帐号，不能重复
	Mobile   string `json:"mobile"` // 手机号，需要单独验证
	NickName string `json:"nick_name"` // 昵称
	Sex      int    `json:"sex"` // 性别:0,未设置;1,男;2,女
	Birthday string    `json:"birthday"` // 生日，时间戳形式，精确到日期
	Age int `json:"age"`
	HeadFile string `json:"head_file"`
}

func GetInfoHandler(c echo.Context) error {
	claims := auth.CurrentUser(c)
	u := new(User)
	if ok, err := x.Where("id = ?", claims.UserID).Get(u); err != nil {
		return errs.Report("xorm", err)
	} else if !ok {
		return errs.Called("用户帐号不存在")
	}

	return resp.Data(c, Info{
		Account:  u.Account,
		Mobile:   u.Mobile,
		NickName: u.NickName,
		Sex:      u.Sex,
		Birthday: format.Date(u.Birthday),
		Age:      Age(u.Birthday),
		HeadFile:GetUserHeadFile(u.HeadID),
	})
}

func UpdateInfoHandler(c echo.Context) error {
	uid := auth.CurrentUser(c).UserID
	i := new(struct{
		NickName string `json:"nick_name"` // 昵称
		Sex      int    `json:"sex"`       // 性别:0,未设置;1,男;2,女
		Birthday int64  `json:"birthday"`  // 生日，时间戳形式，精确到日期
	})
	if err := c.Bind(i); err != nil {
		return err
	}
	if _, err := x.Table(new(User)).Where("id = ?", uid).MustCols("nick_name", "sex", "birthday").Update(i); err != nil {
		return err
	}
	return nil
}

func UpdatePasswordHandler(c echo.Context) error {
	uid := auth.CurrentUser(c).UserID
	i := new(struct{
		OldPassword string `json:"old_password"`
		NewPassword string `json:"new_password"`
	})
	if err := c.Bind(i); err != nil {
		return err
	}
	if i.NewPassword == i.OldPassword {
		return errs.Called("新密码不能与旧密码相同")
	}
	u := new(User)
	if ok, err := x.Where("id = ?", uid).Get(u); err != nil {
		return err
	} else if !ok {
		return errs.Called("用户不存在")
	}
	if EncryptPassword(i.OldPassword, u.Salt) != u.Password {
		return errs.Called("旧密码错误")
	}
	salt := RandSlat()
	if _, err := x.Where("id = ?", uid).Update(&User{
		Password: EncryptPassword(i.NewPassword, salt),
		Salt:     salt,
	}); err != nil {
		return err
	}
	return nil
}
